package Context
{
    import Page.Page;
    import Page.PageSet;
    
    import Regex.Regex;
    import Regex.RegexFile;
    
    import flash.filesystem.File;
    import flash.filesystem.FileMode;
    import flash.filesystem.FileStream;
    import flash.geom.Rectangle;
    
    import mx.collections.ArrayCollection;
    import mx.controls.Alert;
    import mx.core.UIComponent;
    
    [Event(name=Event.CHANGE, type="flash.events.Event")]
    
    [Bindable]
    public class Context extends UIComponent
    {
        private static const DEFAULT_REGEX_FILE_NAME:String = "Twister.regex";
        private static const TWISTER_CONFIG_FILE_NAME:String = "Twister.cfg";
        private static const QUOTES_REGEX_SOURCE:Object 
            = /([^\s\(-]?)"(\s*)([^\\]*?(\\.[^\\]*)*)(\s*)("|^\r)([^\s\)\.\,;:-]?)/img;
    
        
        private static const REGEX_MODE:Number = 0;
        private static const QUOTES_MODE:Number = 1;
    
        private var _mode:Number = REGEX_MODE;
        private var _page_set:PageSet;
        private var _activeFolder:File;
        private var _activePage:Page;
        private var _activeRegexFile:RegexFile;
        private var _rectangle:Rectangle;
//        private var _charset:String = "iso-8859-1";
        private var _charset:String = "utf-8";
        private var _versionString:String;
        private var _fontSize:String = "18";
//        private var _fontFamily:String = "_typewriter";
        private var _fontFamily:String = "DejaVu Sans Mono";
        private var _regex_list_index:Number = 0;
        private var _active_regex:Regex;
        private var _quotes_regex:Regex;
        private var _is_quotes_regex:Regex;
//        private var _regex_collection:ArrayCollection = new ArrayCollection();
                
        public function Context()
        {
            this._quotes_regex = new Regex(QUOTES_REGEX_SOURCE);
        }
        
        public function get FontFamily():String {
            return _fontFamily;
        }
        
        public function set FontFamily(s:String):void {
            _fontFamily = s;
        }
        
        public function get FontSize():String {
            return _fontSize;
        }

        public function set FontSize(s:String):void {
            _fontSize = s;
        }        
        
        public function get Charset():String {
            return _charset;
        }
        
        public function set Charset(cset:String):void {
            _charset = cset;
        }
        
        private function get versionString():String {
            return _versionString;
        }
        
        private function set versionString(s:String):void {
            _versionString = s;
        }
 
        public function get RegexListIndex():Number {
            return _regex_list_index;
        }
        
        public function set RegexListIndex(i:Number):void {
//            this._ad_hoc_regex = null;
            if(i != _regex_list_index) {
                _regex_list_index = i;    
            }
//                _voluntary_regex = null;
            _active_regex = _activeRegexFile.Regexes.getItemAt(i) as Regex;
        }
        
        public function set ActiveRegex(r:Regex):void {
            _active_regex = r;
        }
        
        public function SetRegexMode():void {
            _mode = REGEX_MODE;            
        }
        
        public function SetQuotesMode():void {
            _mode = QUOTES_MODE;
        }
        
        public function get QuotesRegex():Regex {
            return this._quotes_regex;
        }

        public function get IsQuotesMode():Boolean {
            return _mode == QUOTES_MODE;
        }
        
        public function get ActiveRegex():Regex {
            return _active_regex;
//            if(this.IsQuotesRegexMode) {
//                return this.QuotesRegex;
//            } else if(_ad_hoc_regex) {
//                return _ad_hoc_regex;
//            } else if(RegexListIndex >= 0) {
//                return this.RegexCollection.getItemAt(this.RegexListIndex) as Regex;
//            } else {
//                return null;
//            }
        }
        
//        public function SetVoluntaryRegex(ar:Regex):void {
////            _voluntary_regex = ar;   
////            this._ad_hoc_regex = ar;
//            _active_regex = ar;
//        }
        
//        public function get findLast():Boolean {
//            return gContext.FindLast();
////            return ActiveRegex.findLast(activePage.text);
//        }
//        
//        public function LastMatch():Boolean {
//            return ActivePage.LastMatch(ActiveRegex);
//        }
        
        public function setPage(index:int):void {
            ActivePage = getPage(index);
        }
        
        public function getPage(index:int):Page {
            return Pages.getPage(index);    
        }
        
//        public function PrevMatch(index:int):Boolean {
//            var _is:Boolean = ActivePage.PrevMatch(ActiveRegex, index);
//            return _is;
//        }
        
//        public function NextMatch(index:int):Boolean {
//            var _is:Boolean = ActivePage.NextMatch(ActiveRegex, index);
//            return _is;
//        }
//
//        public function get FoundString():String {
//            return ActivePage.FoundString;
////            return ActiveRegex.FoundString;
//        }
//        
//        public function get FoundStringIndex():int {
//            if(!FoundString) {
//                return 0;
//            } else {
//                return ActivePage.FoundStringIndex;
//            }
//        }
//        
//        public function get FoundStringLength():int {
//            if(!FoundString) {
//                return 0;
//            } else {
//                return ActivePage.FoundStringLength;
//            }
//        }
//        
//        public function set QuotesRegexPattern(s:String):void {
//        }
//        
//        public function get QuotesRegexPattern():String {
//            return this._quotes_regex.Pattern;   
//        }
//        
        public function MatchCount(re:Regex):Number {
            var n:Number = 0;
            if( ! re) {
                return 0;
            }
            for each(var p:Page in this.Pages) {
                n += p.MatchCount(re);
            }
            return n;
        }
        
//        public function ResultString(str:String):String {
//            if(! ActiveRegex) {
//                return "";
//            }
//            
//            var re:RegExp = new RegExp(ActiveRegex.PatternString, ActiveRegex.Flags);
//            var s:String = str.replace(re, ActiveRegex.ReplacePattern);
//            return s;
//                
//        }
//
        public function setActiveRegexFile(pFile:File):void {
            _activeRegexFile = new RegexFile(pFile.nativePath);
//            RegexCollection.removeAll();
            
//            for each(var o:Object in _activeRegexFile.Regexes) {
//               if(o[3] == undefined) {
//                   o[3] = "";
//               }
//               if(o[4] == undefined) {
//                   o[4] = "";
//               }
////                RegexCollection.addItem(new Regex(o[1], o[4], o[2], o[3]));
//            }

            RegexListIndex = 0;
        }

        public function set rectangle(rect:Rectangle):void {
            _rectangle = rect;    
        }
        
        public function get rectangle():Rectangle {
            return _rectangle;
        }
        
        public function getRegexAt(i:Number):Regex {
            return _activeRegexFile.Regexes.getItemAt(i) as Regex;
        }
        
//        public function get RegexCollection():ArrayCollection {
//            return _activeRegexFile.Regexes;
////            return _regex_collection;
//        }
//        
       public function serialize():void {
            var o:Object = new Object;
            
            if(ActiveFolder) {
                o.activeFolderPath = ActiveFolder.nativePath;
            }
            if(ActiveRegexFile) {
                o.ActiveRegexPath = ActiveRegexFile.nativePath;
            }
            
            if(_rectangle) {
                o.rectangle = _rectangle;
            }
            if(_charset.length > 0) {
                o.charset = _charset;
            }
            
            if(_versionString && _versionString.length > 0) {
                o.versionString = _versionString;
            }
            
            o.fontSize = _fontSize;
            o.fontFamily =  _fontFamily;

            var s:FileStream    = new FileStream();
            s.open(contextFile, FileMode.WRITE);
            s.writeObject(o);
            s.close()
        }
    
    
//        public function Fix1252():void {
//            var re:Regex = new Regex("ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•--˜™š›œžŸ", "gm", "", "1252 80-9F");
//            var o:Object;
//            for each(var pg:Page in this._page_set) {
//                o = re.RegExpExec(pg.text);
//                while(o && o.index > 0) {
//                    pg.text = pg.text.replace(/ƒ/, "f");
//                    pg.text = pg.text.replace(/„/, '"');
//                    pg.text = pg.text.replace(/…/, "...");
//                    pg.text = pg.text.replace(/†/, "*");
//                    pg.text = pg.text.replace(/‡/, "**");
//                    pg.text = pg.text.replace(/ˆ/, "^");
//                    pg.text = pg.text.replace(/‰/, "[0/00]");
//                    pg.text = pg.text.replace(/Š/, "S");
//                    pg.text = pg.text.replace(/‹/, "'");
//                    pg.text = pg.text.replace(/Ž/, "Z");
//                    pg.text = pg.text.replace(/‘/, "'");
//                    pg.text = pg.text.replace(/’/, "'");
//                    pg.text = pg.text.replace(/“/, "'");
//                    pg.text = pg.text.replace(/”/, '"');
//                    pg.text = pg.text.replace(/•/, "*");
//                    pg.text = pg.text.replace(/˜/, "~");
//                    pg.text = pg.text.replace(/™/, "[TM]");
//                    pg.text = pg.text.replace(/š/, "s");
//                    pg.text = pg.text.replace(/›/, "'");
//                    pg.text = pg.text.replace(/œ/, "[oe]");
//                    pg.text = pg.text.replace(/ž/, "z");
//                }
//            }
//        "\x{80}" => "\x{20AC}",
//        "\x{82}" => "\x{201A}",
//        "\x{83}" => "\x{0192}",
//        "\x{84}" => "\x{201E}",
//        "\x{85}" => "\x{2026}",
//        "\x{86}" => "\x{2020}",
//        "\x{87}" => "\x{2021}",
//        "\x{88}" => "\x{02C6}",
//        "\x{89}" => "\x{2030}",
//        "\x{8A}" => "\x{0160}",
//        "\x{8B}" => "\x{2039}",
//        "\x{8C}" => "\x{0152}",
//        "\x{8E}" => "\x{017D}",
//        "\x{91}" => "\x{2018}",
//        "\x{92}" => "\x{2019}",
//        "\x{93}" => "\x{201C}",
//        "\x{94}" => "\x{201D}",
//        "\x{95}" => "\x{2022}",
//        "\x{96}" => "\x{2013}",
//        "\x{97}" => "\x{2014}",
//        "\x{98}" => "\x{02DC}",
//        "\x{99}" => "\x{2122}",
//        "\x{9A}" => "\x{0161}",
//        "\x{9B}" => "\x{203A}",
//        "\x{9C}" => "\x{0153}",
//        "\x{9E}" => "\x{017E}",
//        "\x{9F}" => "\x{0178}"
//        }
    
        public function unserialize():void {
            _activeFolder = File.documentsDirectory;
//        trace(contextFile.nativePath);
            if(! contextFile.exists) {
                virginize();
                return;
            }
            var s:FileStream = new FileStream();
            s.open(contextFile, FileMode.READ);
            var o:Object = s.readObject();
            s.close();
//            trace("unserialize", o);
            if(o.fontSize && parseInt(o.fontSize, 10) > 0) {
                _fontSize = o.fontSize;
            }
            if(o.fontFamily && o.fontFamily.length > 0) {
                _fontFamily = o.fontFamily.toString();
            }
            if(o.charset && o.charset.length > 0) {
                _charset = o.charset;
            }
            
            if(o.versionString && o.versionString.length > 0) {
                _versionString = o.versionString;
            }
            
            if(o.activeFolderPath && o.activeFolderPath.length > 0) {
                var afolder:File = ActiveFolder.resolvePath(o.activeFolderPath);
                if(afolder.exists && afolder.isDirectory) {
                    ActiveFolder = afolder;
                }                   
            }
            
            if(o.ActiveRegexPath && o.ActiveRegexPath.length > 0) {
                this._activeRegexFile = new RegexFile(o.ActiveRegexPath);
//                this._activeRegexFile = this._activeRegexFile.resolvePath(o.ActiveRegexPath);
//                if(afile.exists && (! afile.isDirectory)) {
//                    setActiveRegexFile(afile);
//                }                   
            }
            
            if(o.rectangle) {
                _rectangle = o.rectangle as Rectangle;
            }
        }

        private function get contextFile():File {
            return File.documentsDirectory.resolvePath(TWISTER_CONFIG_FILE_NAME);
            
        }

        public function get ActiveRegexFile():RegexFile {
            return _activeRegexFile;
        }        
//        public function get ActiveRegexFolder():File {
//            return _activeRegexFile.Folder;
//        }
//        
//        public function get ActiveRegexPath():String {
//            if(_activeRegexFile) {
//                return _activeRegexFile.nativePath;
//            } else {
//                return "";
//            }
//        }
        
//        public function set ActiveRegexPath(s:String):void {
//            
//        }
//        
        public function get ActivePage():Page {
//            if((! _activePage) && _page_set) {
//                if( _page_set.length > 0) {
//                    _activePage = _page_set.FirstPage;
//                }
//            }
            return _activePage;
        }
        
        public function get FirstPage():Page {
            if(Pages.length > 0){
                return Pages.FirstPage;
            } else {
                return null;
            }
        }
        
        public function getNextPage(pg:Page):Page {
            var i:int = Pages.getPageIndex(pg);
            if(i < Pages.length - 1) {
                return Pages.getPage(i+1) as Page;
            } else {
                return null;
            }
        }

        public function ClearActivePage():void {
                ActivePage = FirstPage;
        }   
        
//        public function ClearActiveRegex():void {
//            _active_regex = null;
//        }
//             
        public function get ActiveFolder():File {
            return _activeFolder;
        }
        
         private function set ActiveFolder(pFolder:File):void {
             var f:File;
             if( ( _activeFolder === pFolder ) && _page_set ) {
                 return;
             }
             if(! pFolder.isDirectory) {
                Alert.show("Setting ActiveFolder to on-directory <" + pFolder.nativePath + ">");
             }
             if(_page_set) {
                 _page_set.saveMap();
                 _page_set = null;
             }
             
            _activeFolder = pFolder;
            
            Pages = new PageSet(pFolder, _charset);
//            for(var d:File = _activeFolder ; ; d = d.parent) {
//                if(d == null) {
//                    break;
//                }
//                f = d.resolvePath(DEFAULT_REGEX_FILE_NAME);
//                if(f !== null && f.exists) {
//                    setActiveRegexFile(f);   
//                    break; 
//                }
//            }
            setFirstPageActive();
        }
        
        public function get Pages():PageSet {
            return _page_set;
        }
        
        private function set Pages(ifs:PageSet):void {
            _page_set = ifs;
        }
        
        public function get PageCount():int {
            if(_page_set) {
                return _page_set.length;
            }
            else
            {
                return 0;
            }
        }
        
        private function set ActivePage(fi:Page):void {
            if(_activePage === fi) {
                return;
            }
            if(fi !== null) {
                _activePage = fi;
            } else {
                _activePage = null;
            }
            
        }
        
        public function setFirstPageActive():void {
            if( _page_set ) {
                ActivePage = _page_set.FirstPage;
            }
            else {
                ActivePage = null;
            }
        }
        
        public function setLastPageActive():void {
            if( _page_set ) {
                ActivePage = _page_set.LastPage;
            }
            else {
                ActivePage = null;
            }
        }

        public function IncrementActivePage():void {
            if(!ActivePage) {
                return;
            }
            var i:int = ActivePage.index;
            if(i < Pages.length-1) {
                ActivePage = Pages.getPage(i+1) as Page;
            }   
            else {
                this.setFirstPageActive();
            }
        }    

        public function DecrementActivePage():void {
            if(! ActivePage) {
                return;
            }
            var i:int = ActivePage.index;
            if(i > 0) {
                ActivePage = Pages.getPage(i-1) as Page;
            }   
            else {
                this.setLastPageActive();
            }
        }    

        public function virginize():void {
            if(contextFile.exists) {
                contextFile.deleteFile();
            }
            ActiveFolder = File.documentsDirectory;
            serialize();
        }
    }

}